<!doctype html>
<html>
  <head>
    <meta charset="utf-8">
    <title>CodeMirror: Range Collapsing Demo</title>
    <link rel="stylesheet" href="../lib/codemirror.css">
    <script src="../lib/codemirror.js"></script>
    <script src="../addon/fold/collapserange.js"></script>
    <script src="../mode/javascript/javascript.js"></script>
    <link rel="stylesheet" href="../doc/docs.css">

    <style type="text/css">
      .CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}
      .CodeMirror-collapserange { width: .6em; }
    </style>
  </head>
  <body>
    <h1>CodeMirror: Range Collapsing Demo</h1>

    <form><textarea id="code" name="code">(function() {
  CodeMirror.defineOption("collapseRange", false, function(cm, val, old) {
    var wasOn = old && old != CodeMirror.Init;
    if (val && !wasOn)
      enableRangeCollapsing(cm);
    else if (!val && wasOn)
      disableRangeCollapsing(cm);
  });

  var gutterClass = "CodeMirror-collapserange";

  function enableRangeCollapsing(cm) {
    cm.on("gutterClick", gutterClick);
    cm.setOption("gutters", (cm.getOption("gutters") || []).concat([gutterClass]));
  }

  function disableRangeCollapsing(cm) {
    cm.rangeCollapseStart = null;
    cm.off("gutterClick", gutterClick);
    var gutters = cm.getOption("gutters");
    for (var i = 0; i < gutters.length && gutters[i] != gutterClass; ++i) {}
    cm.setOption("gutters", gutters.slice(0, i).concat(gutters.slice(i + 1)));
  }

  function gutterClick(cm, line, gutter) {
    if (gutter != gutterClass) return;

    var start = cm.rangeCollapseStart;
    if (start) {
      var old = cm.getLineNumber(start);
      cm.setGutterMarker(start, gutterClass, null);
      cm.rangeCollapseStart = null;
      var from = Math.min(old, line), to = Math.max(old, line);
      if (from != to) {
        // Finish this fold
        var fold = cm.markText({line: from + 1, ch: 0}, {line: to - 1}, {
          collapsed: true,
          inclusiveLeft: true,
          inclusiveRight: true,
          clearOnEnter: true
        });
        var topLine = cm.setGutterMarker(from, gutterClass, makeMarker(true, true, clear));
        var botLine = cm.setGutterMarker(to, gutterClass, makeMarker(false, true, clear));
        CodeMirror.on(fold, "clear", clear);

        function clear() {
          cm.setGutterMarker(topLine, gutterClass, null);
          cm.setGutterMarker(botLine, gutterClass, null);
          fold.clear();
        }
        return;
      }
    }

    // Start a new fold
    cm.rangeCollapseStart = cm.setGutterMarker(line, gutterClass, makeMarker(true, false));
  }

  function makeMarker(isTop, isFinished, handler) {
    var node = document.createElement("div");
    node.innerHTML = isTop ? "\u25bc" : "\u25b2";
    if (!isFinished) node.style.color = "red";
    node.style.fontSize = "85%";
    node.style.cursor = "pointer";
    if (handler) CodeMirror.on(node, "mousedown", handler);
    return node;
  }
})();
</textarea></form>

    <script>
      var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
        lineNumbers: true,
        collapseRange: true,
        mode: "javascript"
      });
    </script>

    <p>Click on the right side of the gutter, then click again below,
    the code between will collapse. Click on either arrow to expand.
    To use, simply include the collapserange.js file and
    set <code>collapseRange: true</code> in options. </p>

  </body>
</html>
